package components

import (
    "time"
)

type IdWorker struct  {
    bizIdBits uint64
    nodeIdBits uint64
    seqIdBits uint64
    startTimestamp uint64
    timestampLeftShift uint64
    nodeIdLeftShift uint64
    bizIdLeftShift uint64
    nodeIdMax uint64
    nodeIdMin uint64
    bizIdMax uint64
    bizIdMin uint64
    seqIdMax uint64
    seqIdMin uint64
}
// 时间戳45b+bizId 7b+ nodeId 6b+seqId 5b
// 调整各个位数----
var bizIdBits uint64 = 7 //业务code [0~127]
var nodeIdBits uint64 = 6 //节点code[0~63]
var seqIdBits uint64 = 5
var startTimestampUnit uint64 = 1e4
var nowTimestampUnit int64 = 1e5
// ----调整各个位数
var startTimestamp = 1436198400 * startTimestampUnit
var nodeIdMax uint64 = (1 << nodeIdBits) - 1
var nodeIdMin uint64 = 0
var bizIdMax uint64 = (1 << bizIdBits) - 1
var bizIdMin uint64 = 0
var seqIdMax uint64 = (1 << seqIdBits) - 1
var seqIdMin uint64 = 0
func NewIdWorker() *IdWorker {
    return &IdWorker{
        bizIdBits: bizIdBits,
        nodeIdBits: nodeIdBits,
        seqIdBits: seqIdBits,
        startTimestamp: startTimestamp,
        nodeIdMax: nodeIdMax,
        nodeIdMin: nodeIdMin,
        bizIdMax: bizIdMax,
        bizIdMin: bizIdMin,
        seqIdMax: seqIdMax,
        seqIdMin: seqIdMin,
    }
}
//生成id
func (w *IdWorker) GetId(nodeId uint64,  bizId uint64) (id uint64, seq_id uint64, seq_id_no uint64, seq_id_rand uint64, millis_time uint64){
    if nodeId > w.nodeIdMax {
        return id, seq_id, seq_id_no, seq_id_rand, millis_time
    }
    if bizId > w.bizIdMax {
        return id, seq_id, seq_id_no, seq_id_rand, millis_time
    }
    // 取毫秒
    nowTimestamp := uint64(time.Now().UnixNano()/nowTimestampUnit)
    
    seqId := uint64(time.Now().UnixNano()) % w.seqIdMax
    seq_id = seqId
    id = nowTimestamp - w.startTimestamp
    millis_time = id
    id = id << w.nodeIdBits | nodeId
    id = id << w.bizIdBits | bizId
    id = id << w.seqIdBits | seqId
    //fmt.Println(uint64((1<<64)-1))
    //18446744073709551616
    return
}
//解析node id
func (w *IdWorker) GetNodeId(id uint64) uint64 {
    // >>
    return id >> (w.seqIdBits + w.bizIdBits) & w.nodeIdMax
}
//解析biz id
func (w *IdWorker) GetBizId(id uint64) uint64 {
    //fmt.Println(w.bizIdBits)
    return (id >> w.seqIdBits) & w.bizIdMax
}
